package cn.virens.web.components.mybatis;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.executor.BatchResult;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.defaults.DefaultSqlSession;

import cn.virens.exception.APIException;

/**
 * SqlSession实现读写数据源切换
 * 
 * @author virens
 */
public class VirSqlSession implements SqlSession {
	private final DefaultSqlSession writeSqlSession;
	private final DefaultSqlSession readSqlSession;

	public VirSqlSession(Configuration configuration, Executor readExecutor, Executor writeExecutor, boolean autoCommit) {
		this.writeSqlSession = new DefaultSqlSession(configuration, writeExecutor, autoCommit);
		this.readSqlSession = new DefaultSqlSession(configuration, readExecutor, autoCommit);
	}

	@Override
	public int insert(String statement) {
		return writeSqlSession.insert(statement);
	}

	@Override
	public int insert(String statement, Object parameter) {
		return writeSqlSession.insert(statement, parameter);
	}

	@Override
	public int delete(String statement) {
		return writeSqlSession.delete(statement);
	}

	@Override
	public int delete(String statement, Object parameter) {
		return writeSqlSession.delete(statement, parameter);
	}

	@Override
	public int update(String statement) {
		return writeSqlSession.update(statement);
	}

	@Override
	public int update(String statement, Object parameter) {
		return writeSqlSession.update(statement, parameter);
	}

	@Override
	public <T> T selectOne(String statement) {
		return readSqlSession.selectOne(statement);
	}

	@Override
	public <T> T selectOne(String statement, Object parameter) {
		return readSqlSession.selectOne(statement, parameter);
	}

	@Override
	public <E> List<E> selectList(String statement) {
		return readSqlSession.selectList(statement);
	}

	@Override
	public <E> List<E> selectList(String statement, Object parameter) {
		return readSqlSession.selectList(statement, parameter);
	}

	@Override
	public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
		return readSqlSession.selectList(statement, parameter, rowBounds);
	}

	@Override
	public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
		return readSqlSession.selectMap(statement, mapKey);
	}

	@Override
	public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
		return readSqlSession.selectMap(statement, parameter, mapKey);
	}

	@Override
	public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
		return readSqlSession.selectMap(statement, parameter, mapKey, rowBounds);
	}

	@Override
	public <T> Cursor<T> selectCursor(String statement) {
		return readSqlSession.selectCursor(statement);
	}

	@Override
	public <T> Cursor<T> selectCursor(String statement, Object parameter) {
		return readSqlSession.selectCursor(statement, parameter);
	}

	@Override
	public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
		return readSqlSession.selectCursor(statement, parameter, rowBounds);
	}

	@Override
	@SuppressWarnings("rawtypes")
	public void select(String statement, Object parameter, ResultHandler handler) {
		readSqlSession.select(statement, parameter, handler);
	}

	@Override
	@SuppressWarnings("rawtypes")
	public void select(String statement, ResultHandler handler) {
		readSqlSession.select(statement, handler);
	}

	@Override
	@SuppressWarnings("rawtypes")
	public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
		readSqlSession.select(statement, parameter, rowBounds, handler);
	}

	@Override
	public void close() {
		writeSqlSession.close();
		readSqlSession.close();
	}

	@Override
	public void commit() {
		this.commit(false);
	}

	@Override
	public void commit(boolean force) {
		writeSqlSession.commit(force);
		readSqlSession.commit(force);
	}

	@Override
	public void rollback() {
		this.rollback(false);
	}

	@Override
	public void rollback(boolean force) {
		writeSqlSession.rollback(force);
		readSqlSession.rollback(force);
	}

	@Override
	public void clearCache() {
		writeSqlSession.clearCache();
		readSqlSession.clearCache();
	}

	@Override
	public List<BatchResult> flushStatements() {
		List<BatchResult> answer = new ArrayList<>();
		answer.addAll(writeSqlSession.flushStatements());
		answer.addAll(readSqlSession.flushStatements());

		return answer;
	}

	@Override
	public Configuration getConfiguration() {
		return readSqlSession.getConfiguration();
	}

	@Override
	public <T> T getMapper(Class<T> type) {
		return readSqlSession.getMapper(type);
	}

	@Override
	public Connection getConnection() {
		throw new APIException("ERROR", "多数据源，禁止获取连接");
	}

}
